using Infrastructure.Attribute;
using ZR.Model.BaseManage.Dto;
using ZR.Model.BaseManage;
using ZR.Repository;
using ZR.Service.BaseManage.IBaseManageService;
using Infrastructure;
using Infrastructure.Extensions;
using System.Collections.Generic;
using ZR.Model.System.Dto;
using System.Diagnostics;
using System.Threading.Tasks;
using Aliyun.OSS;

namespace ZR.Service.BaseManage
{
    /// <summary>
    /// 物料信息Service业务层处理
    /// </summary>
    [AppService(ServiceType = typeof(IBaseMaterialService), ServiceLifetime = LifeTime.Transient)]
    public class BaseMaterialService : BaseService<BaseMaterial>, IBaseMaterialService
    {
        /// <summary>
        /// 查询物料信息列表
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        public PagedInfo<BaseMaterialDto> GetPageList(BaseMaterialQueryDto parm)
        {
            var predicate = QueryExp(parm);

            var response = Queryable()
                .Where(predicate.ToExpression())
                .ToPage<BaseMaterial, BaseMaterialDto>(parm);

            return response;
        }


        /// <summary>
        /// 获取详情
        /// </summary>
        /// <param name="MaterialId"></param>
        /// <returns></returns>
        public BaseMaterial GetInfo(string MaterialId)
        {
            var response = Queryable()
                .Where(x => x.MaterialId == MaterialId)
                .First();

            return response;
        }

        /// <summary>
        /// 添加物料信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public BaseMaterial AddBaseMaterial(BaseMaterial model)
        {
            if (this.Any(it => it.MaterialCode == model.MaterialCode))
            {
                throw new CustomException($"系统中已包含{model.MaterialCode}编码信息");
            }
            return Insertable(model).ExecuteReturnEntity();
        }

        /// <summary>
        /// 修改物料信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public int UpdateBaseMaterial(BaseMaterial model)
        {
            if (this.Any(it => it.MaterialCode == model.MaterialCode && it.MaterialId != model.MaterialId))
            {
                throw new CustomException($"系统中已包含{model.MaterialCode}编码信息");
            }
            return Update(model, true);
        }

        /// <summary>
        /// 导入物料信息
        /// </summary>
        /// <returns></returns>
        public (string, object, object) ImportBaseMaterial(List<BaseMaterial> list)
        {
            //获取物料信息
            List<string> codes = list.Select(x => x.MaterialCode).Distinct().ToList();
            List<BaseMaterial> materialList = Context.Queryable<BaseMaterial>().Where(it => codes.Contains(it.MaterialCode)).ToList();
            list.ForEach(it =>
            {
                BaseMaterial oldMaterial = materialList.FirstOrDefault(q => q.MaterialCode == it.MaterialCode);
                if (oldMaterial != null)
                {
                    it.MaterialId = oldMaterial.MaterialId;
                    it.VerifyCode = oldMaterial.VerifyCode;
                    it.VerifyStart = oldMaterial.VerifyStart;
                    it.VerifyState = oldMaterial.VerifyState;
                }
            });

            var x = Context.Storageable(list)
                .SplitUpdate(it => it.Any())//数据库存在更新 根据主键
                .SplitInsert(it => true)//其余插入
                .SplitError(x => x.Item.MaterialId.IsEmpty(), "物料id不能为空")
                .SplitError(x => x.Item.MaterialCode.IsEmpty(), "物料编号不能为空")
                .SplitError(x => x.Item.MaterialType.IsEmpty(), "物料类型不能为空")
                .SplitError(x => x.Item.VerifyStart.IsEmpty(), "验证起始位不能为空")
                .SplitError(x => x.Item.VerifyState.IsEmpty(), "是否验证（0不验证 1验证）不能为空")
                .ToStorage();
            x.AsInsertable.PageSize(1000).ExecuteCommand();//插入可插入部分;
            x.AsUpdateable.PageSize(1000).ExecuteCommand();//插入可更新部分;

            string msg = $"插入{x.InsertList.Count} 更新{x.UpdateList.Count} 错误数据{x.ErrorList.Count} 不计算数据{x.IgnoreList.Count} 删除数据{x.DeleteList.Count} 总共{x.TotalList.Count}";
            Console.WriteLine(msg);

            return (msg, x.ErrorList, x.IgnoreList);
        }

        /// <summary>
        /// 导出物料信息
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        public PagedInfo<BaseMaterialDto> ExportList(BaseMaterialQueryDto parm)
        {
            var predicate = QueryExp(parm);

            var response = Queryable()
                .Where(predicate.ToExpression())
                .Select((it) => new BaseMaterialDto()
                {
                    //MaterialTypeLabel = it.MaterialType.GetConfigValue<Model.System.SysDictData>("material_type"),
                }, true)
                .ToPage(parm);

            return response;
        }

        /// <summary>
        /// 查询导出表达式
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        private static Expressionable<BaseMaterial> QueryExp(BaseMaterialQueryDto parm)
        {
            var predicate = Expressionable.Create<BaseMaterial>();

            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.MaterialCode), it => it.MaterialCode == parm.MaterialCode);
            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.MaterialChLan), it => it.MaterialChLan.Contains(parm.MaterialChLan));
            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.MaterialEngLan), it => it.MaterialEngLan.Contains(parm.MaterialEngLan));
            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.MaterialType), it => it.MaterialType == parm.MaterialType);
            return predicate;
        }

        /// <summary>
        /// 物料信息推送
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public async Task<bool> CogradientMaterial(List<WmsMaterialDto> list)
        {
            if (list == null || list.Count == 0) throw new CustomException("推送的物料信息为空");

            //获取所有的物料信息 
            List<string> codes = list.Select(x => x.partCode).Distinct().ToList();
            List<BaseMaterial> oldList = await Queryable().Where(it => codes.Contains(it.MaterialCode)).ToListAsync();

            List<BaseMaterial> addList = new List<BaseMaterial>();
            List<BaseMaterial> updateList = new List<BaseMaterial>();

            //封装数据
            foreach (var item in list)
            {
                BaseMaterial material = oldList.Where(it => it.MaterialCode == item.partCode).FirstOrDefault();
                if (material != null)
                {
                    //修改
                    material.MaterialChLan = item.partDesc;
                    material.MaterialEngLan = item.partDescEn;
                    material.MaterialUnitBase = item.unitBase;
                    material.MaterialWeightDesign = item.weightDesign;
                    material.MaterialWeight = item.weight;
                    material.MaterialLength = item.length;
                    material.MaterialWidth = item.width;
                    material.MaterialHeight = item.height;
                    material.UpdateBy = "wms";
                    material.UpdateTime = DateTime.Now;
                    updateList.Add(material);
                }
                else
                {
                    material = new BaseMaterial()
                    {
                        MaterialId = Guid.NewGuid().ToString().ToUpper(),
                        MaterialCode = item.partCode,
                        MaterialChLan = item.partDesc,
                        MaterialEngLan = item.partDescEn,
                        MaterialType = "其他",
                        MaterialUnitBase = item.unitBase,
                        MaterialWeightDesign = item.weightDesign,
                        MaterialWeight = item.weight,
                        MaterialLength = item.length,
                        MaterialWidth = item.width,
                        MaterialHeight = item.height,
                        VerifyStart = 0,
                        VerifyState = 0,
                        CreateBy = "wms",
                        CreateTime = DateTime.Now
                    };
                }

            }

            //执行事务
            var db = this.Context.Ado;
            var res = await db.UseTranAsync(async () =>
            {
                if (addList.Count > 0)
                {
                    await db.Context.Insertable(addList).ExecuteCommandAsync();
                }
                if (updateList.Count > 0)
                {
                    await db.Context.Updateable(updateList).ExecuteCommandAsync();
                }
                return true;
            });
            if (res.Data == false)
            {
                throw new CustomException(res.ErrorMessage);
            }

            return true;
        }
    }
}